#include "jeu.h"

#define MAX_PIONS 28

int sema_set_id = 0;
int shmID = 0; /* id de la memoire partagee */
int shmIDrc = 0;
int nbrJoueurs = 0;
int nbrPionsParJoueur = 0;
int joueurs[MAX_JOUEURS];
int serveurSocket = 0;
int maxFdp = 0;
int pions[MAX_PIONS]; /* pions à repartir et à melanger à chaque partie */

fd_set * ensemble_lecture;
/* adresse à laquelle on va attacher la memoire partagee */
sharedMem* shmAddr;
sharedCounter * shmCountAddr;
/* Copie de la memoire partagee, on ecrira dans ce pointeur pour pouvoir lire dedans */
sharedMem * serverMemory;
/* Doit servir dans le cas où un lecteur meurt pendant une lecture */
/* sharedCounter * serverCounter; */
int ** pionsJoueurs; /* stocke les pions de chaque joueur */

int sem_key = 424242;
int shm_key = 654575;
int shmrc_key = 341426;
int lockfile = 0;

void partie(int sck, int lock) {
	message msg;

	struct itimerval old;
	struct itimerval tv;
	static struct sigaction sig;
	struct sigaction sigInt;

	serveurSocket = sck;
	maxFdp = serveurSocket;
	lockfile = lock;

	/* initialisation de la structure sigaction pour catcher
	 *  le signal qui sera declenche après un ctrl+c */
	sigInt.sa_flags = 0;
	sigInt.sa_handler = signalIntHandler;

	/* On se met à l'ecoute du signal SIGINT emit par un administrateur */
	SYSS(sigaction(SIGINT, &sigInt, NULL));

	/* Timer pour une reponse client */
	tv.it_interval.tv_sec = 0;
	tv.it_interval.tv_usec = 0;
	tv.it_value.tv_sec = NOM_TIMEOUT_SERV;
	tv.it_value.tv_usec = 0;

	/* Permet de faire un reset du timer */
	old.it_interval.tv_sec = 0;
	old.it_interval.tv_usec = 0;
	old.it_value.tv_sec = 0;
	old.it_value.tv_usec = 0;

	sig.sa_flags = SA_RESTART;
	sigemptyset(&sig.sa_mask);
	sig.sa_handler = signalHandler;

	/* On se met à l'ecoute du signal SIGALRM emit par le timer */
	SYSS(sigaction(SIGALRM, &sig, NULL));
	/* L'initialisation ne se fait qu'une seule fois */
	initialiserLesRessources();
	/* Un tour de boucle signifie une partie sur le serveur */
	/* Remarque, */
	for (;;) {

		nettoyerRessources();

		/**************************************************************************/
		/** connexion de nouveaux clients */
		accepterJoueurs();

		/* Le timer doit s'arrêter ici sous peine de casser les prochains select
		 * le select est un appel système qui ne redemarre pas après un SIGALRM */
		SYSS(setitimer(ITIMER_REAL, &old, NULL));

		/* On ne continue pas le reste des operations si le nombre de joueurs
		 * minimum n'est pas atteint */

		/* On reinitialise toutes les ressources communes à chaque partie */
		msg.type = CLOSE;
		strcpy(msg.content, "Il n'y a pas assez de joueur");

		if (pasAssezDeJoueurs(&msg))
			continue;

		/**************************************************************************/
		/* demarre une partie de domemo
		 on doit distribuer aleatoirement les pions et les envoyer
		 à chaque joueurs ( sauf leurs pions ) */

		serveurSocket = sck;

		/*****************/
		/* Initialisation du message d'accueil des joueurs */
		msg.type = BIENVENUE;
		strcpy(msg.content, "Bienvenue sur le serveur de jeu Domemo");
		ecrireAuxJoueurs(&msg);
		bzero(&msg, sizeof(message));

		/**************************************************************************/
		enregistrerNomsJoueurs();

		if (nbrJoueurs < MINPLAYERS)
			continue;

		initialiserLesPions();

		/* on sauve le nombre de joueurs dans la copie de la memoire partagee */
		serverMemory->joueurs = nbrJoueurs;
		redacteur(serverMemory, shmAddr, sema_set_id);

		/* partage des ressources */
		envoiDesResources();

		distribuerLesPions(pionsJoueurs);

		tourDeJeu();
	}
}

void tourDeJeu() {
	int tour; /* compteur de tour cyclique, revient à zero à la fin d'un tour de table des joueurs */
	/* Au fur et à mesure d'une partie, les deconnexions peuvent survenir
	 il faut donc prendre dans le tableau des joueurs le nième socket,
	 nième correspondant à la valeur de tour  */
	int numJoueurTableau;
	int j;
	int k;
	tour = 0;
	k = 0;

	while (1) {

		int suivant;
		/* Si le descripteur en cour existe on traite la lecture
		 * et que le descripteur est different de mySocket */
		int event;
		int readBytes;
		struct sockaddr_in client;
		int clientSocket;
		fd_set rfds;
		message msg;
		socklen_t adr_len_cli;
		suivant = 1;
		bzero(&msg, sizeof(message));
		msg.type = GAGNANT_PAR_DEFAUT;
		sprintf(msg.content, "Tu as gagne par defaut");
		if (pasAssezDeJoueurs(&msg)) {
			return;
		}

		/* Il faut determiner à qui est le tour */
		numJoueurTableau = 0;
		j = 0;
		for (numJoueurTableau = 0; numJoueurTableau < MAX_JOUEURS; numJoueurTableau++) {
			if (joueurs[numJoueurTableau] != 0 && j++ == tour)
				break;
		}

		bzero(&msg, sizeof(message));
		msg.type = PION;
		sprintf(msg.content, "%s, c'est ton tour.", serverMemory->prenom[numJoueurTableau]);

		SYSS(write(joueurs[numJoueurTableau], &msg, sizeof(message)));

		while (suivant) {
			bzero(&msg, sizeof(message));
			msg.type = GAGNANT_PAR_DEFAUT;
			sprintf(msg.content, "Tu as gagne par defaut.");
			if (pasAssezDeJoueurs(&msg)) {
				return;
			}

			/* si selectTest est egal à -1 et errno == EINTR l'alarme a sonne,
			 * si la valeur de selectTest est egal à -1 et errno != EINTR on sort du jeu */
			FD_ZERO(&rfds);
			memcpy(&rfds, ensemble_lecture, sizeof(rfds));

			SYSS(select(maxFdp + 1, &rfds, 0, 0, NULL));

			if (FD_ISSET(serveurSocket, &rfds)) {
				SYSS(clientSocket = accept(serveurSocket,
								(struct sockaddr *) &client, &adr_len_cli));
				/* On vide le buffer dès qu'un client arrive */
				SYSS(fflush(stdout));

				bzero(&msg, sizeof(message));
				msg.type = CLOSE;
				strcpy(msg.content, "La partie a dejà commence");
				SYSS(write(clientSocket, &msg, sizeof(message)));
				SYSS(close(clientSocket));
			}

			else {
				/* On regarde où s'est passe l'evenement */
				for (event = 0; event < MAX_JOUEURS; event++) {
					if (joueurs[event] != 0) {
						/* Le serveur analyse le pion reçu par un joueur */
						if (FD_ISSET(joueurs[event], &rfds)) {
							bzero(&msg, sizeof(message));
							SYSS(readBytes = read(joueurs[event], &msg,
											sizeof(message)));
							if (readBytes != 0 && event == numJoueurTableau) { /* on a lu qqchose du client prevu */
								switch (msg.type) {
								case PION: {/* le client doit se terminer , on ne peut l'accepter pour jouer */
									int trouve;
									int ok;
									trouve = atoi(msg.content);

									if (!trouve) {
										bzero(&msg, sizeof(message));
										msg.type = MESSAGE;
										sprintf(msg.content, "Tu as passe ton tour !");
										write(joueurs[event], &msg,
												sizeof(message));
										bzero(&msg, sizeof(message));
										msg.type = MESSAGE;
										sprintf(msg.content, "Le joueur %d a passe son tour", event+1);
										ecrireAuxJoueursSauf(&msg,
												joueurs[event]);
										suivant = 0;
										tour = (tour + 1) % nbrJoueurs;
										continue;
									}
									ok = 0;
									for (j = 0; j < nbrPionsParJoueur; j++) {
										if (pionsJoueurs[event][j] == trouve) {
											ok = 1;
											pionsJoueurs[event][j] = VIDE;
											break;
										}
									}
									if (ok) {
										for (j = 0; j < nbrPionsParJoueur; j++) {
											if (serverMemory->trouver[event][j]
													== VIDE) {
												serverMemory->trouver[event][j]
														= trouve;
												break;
											}
										}

										if (j == nbrPionsParJoueur - 1) {
											bzero(&msg, sizeof(message));
											msg.type = GAGNANT;
											sprintf(msg.content, " Bravo, tu as trouve tout tes pions !");
											write(joueurs[event], &msg,
													sizeof(message));
											bzero(&msg, sizeof(message));

											msg.type = MESSAGE;
											
											sprintf(msg.content, "La partie est remportee par le joueur n°%d - %s", event+1, serverMemory->prenom[event]);
											ecrireAuxJoueursSauf(&msg,joueurs[event]);

											bzero(&msg, sizeof(message));
											msg.type = CLOSE;
											sprintf(msg.content, "Jeu termine !");
											ecrireAuxJoueurs(&msg);

											return;

										}

										bzero(&msg, sizeof(message));
										msg.type = TROUVE;
										sprintf(msg.content, "Bien joue %s !", serverMemory->prenom[event]);
										write(joueurs[event], &msg,
												sizeof(message));

										bzero(&msg, sizeof(message));
										msg.type = EFFACER_PION;
										sprintf(msg.content, "%d%s%d",event,PION_SEPARATEUR,trouve);
										ecrireAuxJoueurs(&msg);

										bzero(&msg, sizeof(message));
										msg.type = MESSAGE;
										sprintf(msg.content, "Le joueur n°%d - %s a trouve le pion %d.", event+1, serverMemory->prenom[event], trouve);
										ecrireAuxJoueursSauf(&msg,
												joueurs[event]);
										redacteur(serverMemory, shmAddr,
												sema_set_id);
										suivant = 0;

									} else {
										bzero(&msg, sizeof(message));
										msg.type = RATE;
										strcpy(msg.content, "Dommage");
										write(joueurs[event], &msg,
												sizeof(message));

										bzero(&msg, sizeof(message));
										msg.type = MESSAGE;
										sprintf(msg.content, "Le joueur numero %d - %s a propose le pion %d", event+1, serverMemory->prenom[event], trouve);
										ecrireAuxJoueursSauf(&msg,
												joueurs[event]);

										tour = (tour + 1) % nbrJoueurs;
										suivant = 0;
										break;
									}
								}
								default:
									break;
								}
							} else if (readBytes == 0) {
								bzero(&msg, sizeof(message));
								msg.type = MESSAGE;
								sprintf(msg.content, "Le joueur numero %d - %s s'est deconnecte.", event+1, serverMemory->prenom[event]);

								nbrJoueurs--;
								FD_CLR(joueurs[event], ensemble_lecture);
								SYSS(close(joueurs[event]));

								/* Lorsqu'on est en attente du dernier joueur et que celui ci se deconnecte,
								 * il faut demander un pion au premier joueur à la prochaine iteration de la boucle.
								 * Si c'est un joueur autre que celui attendu, le serveur continue d'attendre */
								if (numJoueurTableau == event) {
									suivant = 0;/* On passe au suivant */
									tour = tour % nbrJoueurs;
								}
								else if(tour != 0)
									tour--;

								joueurs[event] = 0;
								maxFd();/* La variable maxFdp doit changer après avoir supprime un joueur */

								serverMemory->joueurs = nbrJoueurs;
								/* On reecrit le changement du nombre de joueurs
								 *  dans la memoire partagee pour qu'il puisse
								 *  être lu par les joueurs */
								redacteur(serverMemory, shmAddr, sema_set_id);
								ecrireAuxJoueurs(&msg);
							}
						}
					}
				}
			}
		}
	}
}

/* Cette fonction comme son nom l'indique accepte les joueurs dans les limites
 * autorisees du jeu c'est à dire 1 minute après la connexion du premier
 * client et n'accepte que 5 (MAXPLAYERS) joueurs maximum */
void accepterJoueurs() {

	struct itimerval timer;
	struct itimerval old;
	/* Timer client */
	timer.it_interval.tv_sec = 0;
	timer.it_interval.tv_usec = 0;
	timer.it_value.tv_sec = CONNEXION_TIMEOUT;
	timer.it_value.tv_usec = 0;

	/* Permet de faire un reset du timer */
	old.it_interval.tv_sec = 0;
	old.it_interval.tv_usec = 0;
	old.it_value.tv_sec = 0;
	old.it_value.tv_usec = 0;

	while (1) {
		int event;
		int selectTest;
		int clientSocket;
		struct sockaddr_in client;
		fd_set rfds;
		socklen_t adr_len_cli = sizeof(client);
		/** copie des listes de sockets
		 * de ensemble_lecture vers rfds
		 */
		FD_ZERO(&rfds);

		memcpy(&rfds, ensemble_lecture, sizeof(rfds));
		/* si selectTest est egal à -1 et errno == EINTR l'alarme a sonne,
		 * si la valeur de selectTest est egal à -1 et errno != EINTR on sort du jeu */
		if ((selectTest = select(maxFdp + 1, &rfds, 0, 0, NULL)) == -1) {
			if (errno == EINTR) {
				/* Le timeout est fini pour l'acceptation des joueurs */
				break;
			}
			fprintf(stderr,
					"Le select dans accepterJoueurs() a renvoye une erreur\n");
			kill(getpid(), SIGINT);
		}

		/* verification de l'arrivee d'evenements sur le socket mySocket */
		if (FD_ISSET(serveurSocket, &rfds)) {
			SYSS(clientSocket = accept(serveurSocket, (struct sockaddr *) &client,
							&adr_len_cli));
			/* On vide le buffer dès qu'un client arrive */
			SYSS(fflush(stdout));

			/* Acceptation des clients tant que nbrJoueurs < MAXPLAYERS */
			if (nbrJoueurs < MAX_JOUEURS) {
				FD_SET(clientSocket, ensemble_lecture);
				if (clientSocket > maxFdp)
					maxFdp = clientSocket;
				joueurs[nbrJoueurs++] = clientSocket;
				if (nbrJoueurs == 1) {
					SYSS(setitimer(ITIMER_REAL, &timer, NULL));
				}
			}
		}

		else {
			/* On regarde où s'est passe l'evenement */
			for (event = 0; event < MAX_JOUEURS; event++) {
				if (joueurs[event] != 0) {
					/* Le serveur analyse le nom reçu par un joueur */
					if (FD_ISSET(joueurs[event], &rfds)) {
						int readBytes;
						message msg;
						bzero(&msg, sizeof(message));
						SYSS(readBytes=read(joueurs[event], &msg, sizeof(message)));
						if (readBytes == 0) { /* on a lu qqchose du serveur */
							int j;
							SYSS(close(joueurs[event]));
							FD_CLR(joueurs[event], ensemble_lecture);
							for (j = event; j < nbrJoueurs - 1; j++) {
								joueurs[j] = joueurs[j + 1];
							}

							joueurs[j] = 0;
							nbrJoueurs--;
							maxFd();/* La variable maxFdp doit changer après avoir supprime un joueur */
							bzero(&msg, sizeof(message));
							msg.type = MESSAGE;
							sprintf(msg.content, "Le joueur numero %d s'est deconnecte.", event+1);
							ecrireAuxJoueurs(&msg);
						}
					}
				}
			}
		}
		if (nbrJoueurs == MAX_JOUEURS)
			break;
		if (nbrJoueurs == VIDE) {
			SYSS(setitimer(ITIMER_REAL, &old, NULL));
		}
	}
}

void enregistrerNomsJoueurs() {
	int i;
	message msg;
	fd_set rfds;
	msg.type = NOM;

	strcpy(msg.content, "Introduisez votre nom suivi d'enter puis votre prenom suivi d'enter");
	ecrireAuxJoueurs(&msg);

	i = 0;

	while (i != nbrJoueurs * 2) {
		/** Si le descripteur en cour existe on traite la lecture
		 * et que le descripteur est different de mySocket */
		int event;
		int readBytes;
		struct sockaddr_in client;
		int clientSocket;
		socklen_t adr_len_cli = sizeof(client);
		FD_ZERO(&rfds);
		memcpy(&rfds, ensemble_lecture, sizeof(rfds));

		/* si selectTest est egal à -1 et errno == EINTR l'alarme a sonne,
		 * si la valeur de selectTest est egal à -1 et errno != EINTR on sort du jeu */
		SYSS(select(FD_SETSIZE, &rfds, 0, 0, NULL));

		/* le client doit se terminer , on ne peut l'accepter pour jouer */
		if (FD_ISSET(serveurSocket, &rfds)) {
			SYSS(clientSocket = accept(serveurSocket, (struct sockaddr *) &client,
							&adr_len_cli));
			/* On vide le buffer dès qu'un client arrive */
			SYSS(fflush(stdout));

			bzero(&msg, sizeof(message));
			msg.type = CLOSE;
			strcpy(msg.content, "La partie a dejà commence");
			SYSS(write(clientSocket, &msg, sizeof(message)));
			SYSS(close(clientSocket));
		}

		else {
			/* On regarde où s'est passe l'evenement */
			for (event = 0; event < MAX_JOUEURS; event++) {
				if (joueurs[event] != 0) {
					/* Le serveur analyse le nom ou le prenom reçu par un joueur */
					if (FD_ISSET(joueurs[event], &rfds)) {
						bzero(&msg, sizeof(message));
						SYSS(readBytes=read(joueurs[event], &msg, sizeof(message)));
						if (readBytes != 0) { /* on a lu quelque chose d'un client */
							switch (msg.type) {
							case NOM: {
								strcpy(serverMemory->nom[event], msg.content);
								i++;
								break;
							}

							case PRENOM: {
								strcpy(serverMemory->prenom[event],msg.content);
								i++;
								break;

							}
							default:
								break;
							}
						} else if (readBytes == 0) {
							int j;
							close(joueurs[event]);
							FD_CLR(joueurs[event], ensemble_lecture);
							for (j = event; j < nbrJoueurs - 1; j++) {
								joueurs[j] = joueurs[j + 1];
							}

							joueurs[j] = 0;
							nbrJoueurs--;
							maxFd();/* La variable maxFdp doit changer après avoir supprime un joueur */
							bzero(&msg, sizeof(message));

							msg.type = CLOSE;
							strcpy(msg.content, "Trop de joueurs se sont deconnectes avant le debut de la partie.");

							if (pasAssezDeJoueurs(&msg))
								return;
							bzero(&msg, sizeof(message));
							msg.type = MESSAGE;
							sprintf(msg.content, "Le joueur numero %d s'est deconnecte.", event+1);
							ecrireAuxJoueurs(&msg);
						}
					}
				}
			}
		}
	}
}

void initialiserLesRessources() {
	/* initialiser les ressources */
	int fd;
	int i, j, k;
	fd = 0;
	sema_set_id = semInit(sem_key, 1);

	shmID = shmInit(shm_key, sizeof(struct sharedMem));
	shmIDrc = shmInit(shmrc_key, sizeof(struct sharedCounter));

	/* on obtient desormais le pointeur vers notre memoire */
	shmAddr = (sharedMem *) shmAttach(shmID, (char*) shmAddr);
	shmCountAddr = (sharedCounter *) shmAttach(shmIDrc, (char *) shmCountAddr);

	SYSM(ensemble_lecture = (fd_set *) malloc(sizeof(fd_set)));
	SYSM(serverMemory = (sharedMem*) malloc(sizeof(sharedMem)));

	k = 0;
	for (i = 0; i < DIFF_CONFIG; i++) {
		for (j = 0; j < DIFF_REPARTITION; j++) {
			serverMemory->repartition[i][j] = REPARTITION[k++] - '0';
		}
	}

	j = MAX_PIONS_PAR_JOUEUR;
	k = 0;
	for (i = TOTAL_PIONS - 1; i >= 0; i--) {
		pions[i] = j;
		k++;
		if (k == j) {
			k = 0;
			j--;
		}
	}
}

void nettoyerRessources() {
	int fd;
	/* on nettoie toutes les structures et variables sauf la table de repartition */

	serverMemory->joueurs = 0;

	bzero(serverMemory->visible, MAX_PIONS_PAR_JOUEUR * sizeof(int));
	for (fd = 0; fd < MAX_JOUEURS; fd++) {
		bzero(serverMemory->nom[fd], LONG_NOM * sizeof(char));
		bzero(serverMemory->prenom[fd], LONG_NOM * sizeof(char));
		bzero(serverMemory->trouver[fd], MAX_PIONS_PAR_JOUEUR * sizeof(int));
	}
	redacteur(serverMemory, shmAddr, sema_set_id);

	nbrJoueurs = 0;
	/** remise à zero de toutes les structures */
	FD_ZERO(ensemble_lecture);

	/** Ajout du socket serveur dans l'ensemble des descripteur à ecouter */
	FD_SET(serveurSocket, ensemble_lecture);

	/** Initialisation du tableau qui contiendra les sockets client */
	for (fd = 0; fd < MAX_JOUEURS; fd++) {
		joueurs[fd] = 0;
	}
}

/* Doit être appele à chaque debut de partie après la methode initialiserLesRessources*/
void initialiserLesPions() {
	int i, j, k;
	int cpt;
	int nbrPionsVisible;
	k = 0;
	/* initialise le tableau des pions des joueurs */

	nbrPionsVisible = serverMemory->repartition[nbrJoueurs - 2][2];

	nbrPionsParJoueur = serverMemory->repartition[nbrJoueurs - 2][0];

	SYSM(pionsJoueurs = (int**) realloc(pionsJoueurs, nbrJoueurs * sizeof(int*)));

	for (i = 0; i < nbrJoueurs; i++) {
		SYSM(pionsJoueurs[i] = (int*) realloc(pionsJoueurs[i], nbrPionsParJoueur
				* sizeof(int)));
	}

	/* appel de la methode pour melanger ce tableau */
	melange(pions, sizeof(pions) / sizeof(int));


	/* repartition des pions entre les differents joueurs et la face visible de la table */
	cpt = 0;

	for (i = 0; i < nbrJoueurs; i++) {
		for (j = 0; j < nbrPionsParJoueur; j++) {
			pionsJoueurs[i][j] = pions[cpt++];
		}
	}

	/* Ecriture des pions visibles dans la memoire du serveur */
	for (i = 0; i < nbrPionsVisible; i++) {
		serverMemory->visible[i] = pions[cpt++];
	}

}

void envoiDesResources(void) {
	message msg;
	/* partage des resources */
	/** envoi de la cle du semaphore */
	bzero(&msg, sizeof(message));
	msg.type = SEMAPHORE_SET_ID;
	sprintf(msg.content, "%d", sema_set_id);
	ecrireAuxJoueurs(&msg);

	/** envoi de la cle de la memoire partagee */
	bzero(&msg, sizeof(message));
	msg.type = SHARED_MEM;
	sprintf(msg.content, "%d", shmID);
	ecrireAuxJoueurs(&msg);

	/* envoi de la cle de la memoire partagee de
	 * l'indice compteur de processus lecteur */
	bzero(&msg, sizeof(message));
	msg.type = SHARED_MEM_RC;
	sprintf(msg.content, "%d", shmIDrc);
	ecrireAuxJoueurs(&msg);
}

void distribuerLesPions(int ** pions) {
	int fds;
	int i, j;
	message messg, numero;
	char pion[2];
	bzero(&messg, sizeof(message));

	messg.type = PIONS_RECUS;
	numero.type = NUMERO;
	/** envoi du message à chaque client */
	for (fds = 0; fds < MAX_JOUEURS; fds++) {
		if (joueurs[fds] != 0) {
			sprintf(numero.content,"%d",fds);
			SYSS(write(joueurs[fds], &numero, sizeof(message)));
			bzero(numero.content, MAXLINE * sizeof(char));
			for (i = 0; i < nbrJoueurs; i++) {
				if (i != fds) {
					for (j = 0; j < nbrPionsParJoueur; j++) {
						sprintf(pion, "%d", pions[i][j]);
						strcat(messg.content, pion);
						strcat(messg.content, PION_SEPARATEUR);
					}
				}
			}
			SYSS(write(joueurs[fds], &messg, sizeof(message)));
			bzero(messg.content, MAXLINE * sizeof(char));
		}
	}
}

int pasAssezDeJoueurs(message * msg) {
	if (nbrJoueurs == GAGNANT_PAR_DEFAUT) {
		ecrireAuxJoueurs(msg);
		return 1;
	}

	if (nbrJoueurs == VIDE) {
		return 1;
	}
	return 0;
}

void ecrireAuxJoueurs(message * messg) {
	int fds;
	/** envoie du message à chaque client */
	for (fds = 0; fds < MAX_JOUEURS; fds++) {
		if (joueurs[fds] != 0) {
			SYSS(write(joueurs[fds], messg, sizeof(message)));
		}
	}
}

void ecrireAuxJoueursSauf(message * messg, int sck) {
	int fds;
	/** envoie du message à chaque client excepte un */
	for (fds = 0; fds < MAX_JOUEURS; fds++) {
		if (joueurs[fds] != 0 && joueurs[fds] != sck) {
			SYSS(write(joueurs[fds], messg, sizeof(message)));
		}
	}
}

void melange(int * array, size_t taille) {
	int i, pion;

	srand(time(NULL));

	for (i = 0; i < (int) taille; i++) {
		int rand_index = rand() % (MAX_PIONS);/* Verifie une bonne repartition des indices */
		pion = array[i];
		array[i] = array[rand_index];
		array[rand_index] = pion;
	}
}

void signalHandler(int signal) {
	if (signal == SIGALRM)
		fprintf(stderr, "JEU.C : Temps ecoule!\n");
}

void maxFd() {
	int i;
	maxFdp = serveurSocket;
	for (i = 0; i < MAX_JOUEURS; i++) {
		if (joueurs[i] > maxFdp)
			maxFdp = joueurs[i];
	}
}

/* Cette fonction a pour mission de ne laisser aucun ipc sur le système et
 * de fermer le serveur proprement */
void signalIntHandler(int signal) {
	int a;
	message msg, msgRc;
	msg.type = CLOSE;
	strcpy(msg.content, "Le serveur est hors-service!");
	fprintf(stderr,"SIGINT : %d\n",signal);
	/* En TCP/IP la fermeture active (FIN) du socket se fait du côte du client
	 * le serveur effectue la fermeture passive (ACK) avec read */

	/* 4 segment par fermeture TCP */
	for (a = 0; a < MAX_JOUEURS; a++) {
		/* Pour chaque fermeture il peut y avoir un delai
		 * du à la congestion reseau*/
		if (joueurs[a] != 0) {
			SYS(write(joueurs[a], &msg, sizeof(message)));/* demande de FIN C */
			SYS(read(joueurs[a], &msgRc, sizeof(message)));/* ACK C+1 */
			SYS(close(joueurs[a]));/* FIN S --> ACK S+1 */
		}

	}

	if (lockfile != 0) {
		SYS(unlink(LOCK));
	}

	if (sema_set_id != 0) {
		SYS(semctl(sema_set_id, 0, IPC_RMID));
	}

	if (shmID != 0) {
		SYS(shmdt(shmAddr));
		SYS(shmctl(shmID, IPC_RMID, NULL));
	}

	if (shmIDrc != 0) {
		SYS(shmdt(shmCountAddr));
		SYS(shmctl(shmIDrc, IPC_RMID, NULL));
	}

	if (serveurSocket != 0) {
		SYS(close(serveurSocket));
	}
	exit(3);
}
